<?php

namespace JsonLowCode;

use Closure;
use JsonLowCode\Factory\TableFactory;
use JsonLowCode\Helps\Random;
use JsonLowCode\Support\Js;
use JsonLowCode\Table\Action;
use JsonLowCode\Table\Column;
use JsonLowCode\Table\Search;
use JsonLowCode\Table\Support\BuildField;

/**
 * Table
 * @method static Table make(Closure $closure) Table
 */
class Table extends TableFactory
{
    /**
     * 元素集合
     * @var array
     */
    protected array $elements = [];
    /**
     * 数据
     * @var array
     */
    protected array $data = [];

    /**
     * @var Closure<array, array, ?Closure>|null
     */
    protected ?Closure $fetchClosure = null;
    /**
     * @var array
     */
    protected array $fetchRequestField = [
        "pageField"=>"page",
        "pageSizeField"=>"pageSize",
        "searchField"=>"search"
    ];
    /**
     * @var array
     */
    protected array $fetchResponseField = [
        "totalField"=>"total",
        "pageCountField"=>"pageCount",
        "dataField"=>"data"
    ];
    /**
     * @var array
     */
    protected array $fetchResult = [];


    /**
     * 总条数
     * @var int
     */
    protected int $total = 0;
    /**
     * 总页数
     * @var int
     */
    protected int $pageCount = 0;

    protected array $tabs = [];

    /**
     * @var array<string,Column>
     */
    protected array $columns = [];
    /**
     * @var array<string,Action>
     */
    protected array $actions = [];

    private $request;

    public $eloquent = null;

    protected string $tableName = "";

    protected ?Column $selection = null;

    protected mixed $searchForm = null;

    /**
     * @var string
     */
    protected string $rowDataField = "__self.rowData";
    /**
     * @var string
     */
    protected string $rowDataIndex = "__self.rowIndex";

    /**
     * 表data数据绑定键
     * @var string
     */
    protected string $bindKey = "";

    protected ?Closure $builder = null;
    protected ?Closure $rowClosure = null;
    protected array|string $keyName = '';

    protected bool $isBuilt = false;
    protected mixed $repository = null;
    protected string $_method = "page";

    public function __construct(Closure $closure)
    {
        parent::__construct();
        $this->ref("tableRef".Random::alpha(10));
        $this->bindKey = "table".Random::alpha(10);
//        $this->eloquent->setTable($this);
        $closure($this);
        $this->build();
    }

    /**
     * 初始化表格
     * @return $this
     */
    public function initTable(): static
    {
        $this->showHeader();
        $this->showHeaderCollapse();
        $this->showTool();
        $this->showPage();
        $this->selection();
        $this->striped();
        return $this;
    }

    /**
     * 注册请求
     * @param Closure<array,array> $fetchClosure
     * @return $this
     */
    public function fetchClosure(Closure $fetchClosure): static
    {
        $this->fetchClosure = $fetchClosure;
        return $this;
    }

    /**
     * @param string $pageField
     * @param string $pageSizeField
     * @param string $searchField
     * @return $this
     */
    public function fetchRequestField(string $pageField = "page",string $pageSizeField = "pageSize",  string $searchField = "search"): static
    {
        $this->fetchRequestField['pageField'] = $pageField;
        $this->fetchRequestField['pageSizeField'] = $pageSizeField;
        $this->fetchRequestField['searchField'] = $searchField;
        return $this;
    }

    /**
     * @param string $totalField
     * @param string $pageCountField
     * @param string $dataField
     * @return $this
     */
    public function fetchResponseField(string $totalField = "total",string $pageCountField = "pageCount", string $dataField = "data"): static
    {
        $this->fetchResponseField['totalField'] = $totalField;
        $this->fetchResponseField['pageCountField'] = $pageCountField;
        $this->fetchResponseField['dataField'] = $dataField;
        return $this;
    }

    /**
     * Set primary key name.
     *
     * @param array|string $name
     * @return $this
     */
    public function setKeyName(array|string $name): static
    {
        $this->keyName = $name;

        return $this;
    }

    /**
     * 设置每页大小
     * @param int $pageSize
     * @return $this
     */
    public function setPageSize(int $pageSize = 10): static
    {
        $this->eloquent->setPerPage($pageSize);
        return $this;
    }

    /**
     * Set rowData
     *
     * @param string $field
     * @param string $index
     * @return $this
     */
    public function setRowData(string $field = "rowData", string $index = "rowIndex"): static
    {
        $this->rowDataField = Js::this($field);
        $this->rowDataIndex = Js::this($index);
        return $this;
    }

    /**
     * Get rowData
     *
     * @return array
     */
    public function getRowData(): array
    {
        return [$this->rowDataField,$this->rowDataIndex];
    }

    /**
     * Get or set primary key name.
     *
     * @return string|array
     */
    public function getKeyName(): array|string
    {
        return $this->keyName ?: 'id';
    }

    /**
     * 获取搜索的字段数组内容
     * @return array
     */
    public function getSearchFormFields(): array
    {
        return $this->searchForm?->getFields();
    }

    public function getSearchWhere(): Closure
    {
        $searchModel = json_decode($this->request->input("searchModel",""),true);
        $search = $this->getSearchFormFields();
        return function ($query) use ($search,$searchModel) {
            foreach ($search as $item){
                if (isset($searchModel[$item['field']])&&$searchModel[$item['field']]){
                    $value = $searchModel[$item['field']];
                    $condition = $item['condition'];
                    $conditions = ['=',">","<",">=","<=","<>"];
//                    if (in_array($condition, $conditions)){
//                        if ($condition=="="){
//                            $query->where($item['field'],$value);
//                        }else{
//                            $query->where($item['field'],$condition,$value);
//                        }
//                    }else{
//                        switch ($condition){
//                            case "like":
//                            case "LIKE":
//                                $value = "%{$value}%";
//                                $query->where($item['field'],strtoupper($condition),$value);
//                                break;
//                            case "BETWEEN":
//                                $query->whereBetween($item['field'],$value);
//                                break;
//                            case "in":
//                            case "IN":
//                                $query->whereIn($item['field'],$value);
//                                break;
//                        }
//                    }
                }
            }
        };
    }

    /**
     * 获取模型
     * @return
     */
    public function eloquent()
    {
        return $this->eloquent;
    }

    /**
     * 获取模型
     */
    public function repository()
    {
        return $this->repository;
    }

    /**
     * @return array
     */
    public function getData(): array
    {
        return $this->data;
    }


    /**
     * @param string $field 字段名称
     * @param string $label 字段描述
     * @return Column
     */
    public function column(string $field, string $label = ""): Column
    {
        $label = $label?:ucfirst($field);
        $column = new Column($field, $label, $this);
        return tap($column,function (Column $column) use ($field) {
            $this->columns[$field] = $column;
        });
    }


    /**
     * 获取columns
     * @return array<Column>
     */
    public function getColumns(): array
    {
        return array_values($this->columns);
    }


    /**
     * @param string $text
     * @param $to
     * @return Action
     */
    public function action(string $text, $to): Action
    {
        $action = new Action($text, $to, $this);
        return tap($action,function (Action $action) {
            $this->actions[] = $action;
        });
    }

    /**
     * 设置搜索表单
     * @param Closure|null $callback
     */
    public function search(Closure $callback = null)
    {
        $this->searchForm = new Search($this, $callback);
        return $this->searchForm;
    }


    /**
     * 设置多选,是否显示多选列
     * @param bool $show
     * @param string|bool $isMultiple true=多选, false=单选
     * @param bool $isJSExpression 是否js表达式
     * @return Column|null
     */
    public function selection(bool $show = true, string|bool $isMultiple = true, bool $isJSExpression = false): Column|null
    {
        if ($show){
            $this->selection = new Column('selection','选择',$this);
            $this->selection->selection($isMultiple, $isJSExpression);
            return $this->selection;
        }else{
            $this->selection = null;
            return null;
        }
    }

    /**
     * 是否显示工具栏
     * @param string|bool $showRightTool
     * @return $this
     */
    public function showTool(bool $showLeftTool = true, bool $showRightTool = true): static
    {
        $this->showLeftTool($showLeftTool);
        $this->showRightTool($showRightTool);
        return $this;
    }

    /**
     * 行数据回调
     * @param Closure $closure
     * @return $this
     */
    public function rowData(Closure $closure): static
    {
        $this->rowClosure = $closure;
        return $this;
    }


    /**
     * @return void
     */
    protected function buildColumns(): void
    {
        $checkedKeys = array_keys(array_filter($this->columns,function (Column $column){
            return $column->checked;
        }));
        if ($checkedKeys){
            $this->defaultCheckedRowKeys($checkedKeys);
        }
        $columns = array_values($this->columns);
        if ($this->selection){
            $columns = array_merge([$this->selection],$columns);
        }
        $this->columns($columns);
    }

    protected function buildActions(): void
    {
        if (!$this->actions){
            $space = UI::space();
            $space->children($this->actions);
            $this->column("_action_","操作")->render($space);
        }
    }

    /**
     * @return void
     */
    protected function buildData(): void
    {
        $this->data = array_map(function ($row){
            if ($this->rowClosure instanceof Closure){
                $result = call_user_func($this->rowClosure,$row);
                if ($result){
                    $row = $result;
                }
            }
            return BuildField::make($row, $this);
        }, $this->data);
        $this->data($this->data);
    }

    /**
     * 搜索重置事件
     * @return string
     */
    public function onReset(): string
    {
        return scriptFunc("{$this->getRef('onReset')}();");
    }

    /**
     * 刷新事件
     * @return string
     */
    public function refresh(): string
    {
        return scriptFunc("{$this->getRef('refresh')}();");
    }

    /**
     * 搜索事件
     * @return string
     */
    public function onSearch(): string
    {
        return scriptFunc("{$this->getRef('onSearch')}();");
    }

    /**
     * @return array|mixed
     */
    public function fetchList(): mixed
    {
        if (!$this->fetchClosure){
            throw new \BadMethodCallException("No Closure fetchClosure Function!");
        }
        $requestField = $this->fetchRequestField;
        $responseField = $this->fetchResponseField;
        $fetch = $this->fetchClosure->bindTo($this, static::class);
        return $fetch($requestField,$responseField, $this->rowClosure);
    }

    protected function build(): static
    {
        if ($this->searchForm){
            $this->slotSearch($this->searchForm);
        }
        $this->buildActions();
        $this->buildColumns();
        return $this;
    }

    public function toArray(): array
    {
        if ($this->_method=='list'){
            return $this->fetchList();
        }else{
            $this->buildData();
            return parent::toArray();
        }
    }

}
